package com.lonni.rpc.core.socket.client;

import com.lonni.rpc.core.model.RpcResponse;
import com.lonni.rpc.core.socket.codec.RpcProtocol;
import io.netty.channel.Channel;
import io.netty.util.concurrent.Promise;
import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;
import java.net.InetSocketAddress;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 保存客户端netty链接
 *
 * @author: Lonni
 * @date: 2024/7/11 0011 9:23
 */
@Slf4j
public class NettyClientContext implements Serializable {

    private NettyClientContext() {
    }

    public static NettyClientContext me = new NettyClientContext();

    /**
     * key ip:port
     * value: channel
     * 保存本地链接缓存
     */
    private final Map<String, Channel> channelMap = new ConcurrentHashMap<>();

    /**
     * 保存requestid和 CompletableFuture的缓存
     */
    private final Map<String, CompletableFuture<RpcProtocol<RpcResponse>>> RESPONSE_FUTURE_MAP = new ConcurrentHashMap<>();


    /**
     * promise方式
     */
    private final Map<String, Promise> RESPONSE_PROMISE = new ConcurrentHashMap<>();


    public Channel getChannel(InetSocketAddress address) {
        String key = address.toString();
        if (channelMap.containsKey(key)) {
            Channel channel = channelMap.get(key);
            if (channel.isActive()) {
                return channel;
            }
        }
        return null;
    }

    public Channel getChannel(String ip, Integer port) {
        InetSocketAddress address = new InetSocketAddress(ip, port);
        return getChannel(address);
    }


    public void setChannel(InetSocketAddress inetSocketAddress, Channel channel) {
        String key = inetSocketAddress.toString();
        channelMap.put(key, channel);

    }

    public void remove(InetSocketAddress inetSocketAddress) {
        String key = inetSocketAddress.toString();
        channelMap.remove(key);
        log.info("Channel map size :[{}]", channelMap.size());
    }


    public void putFuture(String requestId, CompletableFuture<RpcProtocol<RpcResponse>> future) {
        RESPONSE_FUTURE_MAP.putIfAbsent(requestId, future);
    }


    public CompletableFuture<RpcProtocol<RpcResponse>> getFuture(String requestId) {
        return RESPONSE_FUTURE_MAP.getOrDefault(requestId, null);
    }


    public void putPromise(String requestId, Promise promise) {
        RESPONSE_PROMISE.putIfAbsent(requestId, promise);
    }

    public Promise getPromise(String requestId) {
        return RESPONSE_PROMISE.getOrDefault(requestId, null);
    }


    public int getChannelCount() {
        return channelMap.size();
    }

}



